// Code scaffolded by goctl. Safe to edit.
// goctl 1.9.2

package middleware

import (
	"context"
	"net/http"

	"nexus/addon"
	"nexus/utils"
	"nexus/utils/errorx"

	"github.com/zeromicro/go-zero/core/logc"
	"github.com/zeromicro/go-zero/rest/httpx"
)

type TokenMiddleware struct {
	jwt   *utils.JWT
	redis *addon.RedisAddons
}

func NewTokenMiddleware(jwt *utils.JWT, redis *addon.RedisAddons) *TokenMiddleware {
	return &TokenMiddleware{
		jwt:   jwt,
		redis: redis,
	}
}

func (m *TokenMiddleware) Handle(next http.HandlerFunc) http.HandlerFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		// 1. token是否为空
		var token string
		if token = r.URL.Query().Get("Authorization"); token == "" {
			token = r.Header.Get("Authorization")
			if token == "" {
				httpx.Error(w, errorx.TokenInvalid)
				return
			}
		}

		// 2. 解析token
		claim, err := m.jwt.ParseToken(token)
		if err != nil {
			logc.Errorf(context.Background(), "Token解析错误: %v", err)
			httpx.Error(w, errorx.TokenInvalid)
			return
		}

		// 3. 查询redis中是否存在token
		oldToken, err := m.redis.GetKey(r.Context(), claim.UserID)
		if err != nil {
			logc.Errorf(context.Background(), "redis 错误: %v", err)
			httpx.Error(w, errorx.ServerError)
			return
		}
		if token != oldToken {
			httpx.Error(w, errorx.TokenInvalid)
			return
		}

		// 4. 将用户信息存入上下文
		ctx := context.WithValue(r.Context(), utils.CtxKeyUserID, claim.UserID)
		ctx = context.WithValue(ctx, utils.CtxKeyNickname, claim.Nickname)
		ctx = context.WithValue(ctx, utils.CtxKeyTenantID, claim.TenantID)

		// 5. 继续处理请求
		next(w, r.WithContext(ctx))
	}
}
